#!/usr/bin/env python3
"""
日志配置模块
使用 loguru 提供统一的日志管理功能
"""

import logging
import sys
from pathlib import Path
from typing import Any, Optional

from loguru import logger


class LoggingConfig:
    """日志配置管理器"""

    def __init__(self, log_dir: str = "logs", app_name: str = "speech-convert"):
        """
        初始化日志配置

        Args:
            log_dir: 日志文件目录
            app_name: 应用名称
        """
        self.log_dir = Path(log_dir)
        self.app_name = app_name
        self._setup_done = False

    def setup(self, level: str = "INFO", enable_console: bool = True, enable_file: bool = True):
        """
        设置日志配置

        Args:
            level: 日志级别
            enable_console: 是否启用控制台输出
            enable_file: 是否启用文件输出
        """
        if self._setup_done:
            return

        # 创建日志目录
        self.log_dir.mkdir(exist_ok=True)

        # 移除默认的 loguru 处理器
        logger.remove()

        # 控制台输出
        if enable_console:
            logger.add(
                sys.stdout,
                format="<green>{time:YYYY-MM-DD HH:mm:ss}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>",
                level=level,
                colorize=True,
                backtrace=True,
                diagnose=True
            )

        # 文件输出
        if enable_file:
            # 应用日志
            logger.add(
                self.log_dir / f"{self.app_name}.log",
                format="{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {name}:{function}:{line} - {message}",
                level=level,
                rotation="100 MB",
                retention="30 days",
                compression="zip",
                backtrace=True,
                diagnose=True
            )

            # 错误日志单独文件
            logger.add(
                self.log_dir / f"{self.app_name}_error.log",
                format="{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {name}:{function}:{line} - {message}",
                level="ERROR",
                rotation="50 MB",
                retention="60 days",
                compression="zip",
                backtrace=True,
                diagnose=True
            )

            # 性能日志
            logger.add(
                self.log_dir / f"{self.app_name}_performance.log",
                format="{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {name}:{function}:{line} - {message}",
                level="INFO",
                rotation="50 MB",
                retention="30 days",
                compression="zip",
                filter=lambda record: "performance" in record["extra"]
            )

        # 替换标准库的 logging
        self._intercept_standard_logging()

        # 设置第三方库的日志级别
        self._configure_third_party_logging()

        self._setup_done = True
        logger.info(f"✅ 日志系统初始化完成 - 级别: {level}")

    def _intercept_standard_logging(self):
        """拦截标准库的 logging"""
        class InterceptHandler(logging.Handler):
            def emit(self, record: logging.LogRecord) -> None:
                try:
                    level = logger.level(record.levelname).name
                except ValueError:
                    level = record.levelno

                frame, depth = logging.currentframe(), 2
                while frame and frame.f_code.co_filename == logging.__file__:
                    frame = frame.f_back
                    depth += 1

                logger.opt(depth=depth, exception=record.exc_info).log(level, record.getMessage())

        logging.basicConfig(handlers=[InterceptHandler()], level=0, force=True)

    def _configure_third_party_logging(self):
        """配置第三方库的日志级别"""
        # FastAPI 和 Uvicorn
        logging.getLogger("uvicorn.access").setLevel(logging.WARNING)
        logging.getLogger("uvicorn.error").setLevel(logging.WARNING)
        logging.getLogger("fastapi").setLevel(logging.WARNING)

        # AI 模型相关
        logging.getLogger("modelscope").setLevel(logging.ERROR)
        logging.getLogger("funasr").setLevel(logging.ERROR)
        logging.getLogger("jieba").setLevel(logging.ERROR)
        logging.getLogger("torch").setLevel(logging.WARNING)
        logging.getLogger("torchaudio").setLevel(logging.WARNING)

        # WebSocket
        logging.getLogger("websockets").setLevel(logging.WARNING)

        # 其他
        logging.getLogger("asyncio").setLevel(logging.WARNING)
        logging.getLogger("urllib3").setLevel(logging.WARNING)
        logging.getLogger("requests").setLevel(logging.WARNING)


class LoggerMixin:
    """日志混入类，为类提供日志功能"""

    @property
    def logger(self):
        """获取当前类的日志器"""
        return logger.bind(module=self.__class__.__name__)


def get_logger(name: Optional[str] = None) -> Any:
    """
    获取日志器

    Args:
        name: 日志器名称

    Returns:
        loguru logger 实例
    """
    if name:
        return logger.bind(module=name)
    return logger


def log_performance(func_name: str, duration: float, **kwargs: object) -> None:
    """
    记录性能日志

    Args:
        func_name: 函数名称
        duration: 执行时间（秒）
        **kwargs: 其他参数
    """
    logger.bind(performance=True).info(
        f"性能监控 - {func_name}",
        duration=f"{duration:.3f}s",
        **kwargs
    )


def log_api_request(method: str, path: str, status_code: int, duration: float, **kwargs: object) -> None:
    """
    记录 API 请求日志

    Args:
        method: HTTP 方法
        path: 请求路径
        status_code: 状态码
        duration: 处理时间（秒）
        **kwargs: 其他参数
    """
    level = "ERROR" if status_code >= 400 else "INFO"
    logger.bind(api_request=True).log(
        level,
        f"API 请求 - {method} {path}",
        status_code=status_code,
        duration=f"{duration:.3f}s",
        **kwargs
    )


def log_websocket_event(event_type: str, client_id: str, **kwargs: object) -> None:
    """
    记录 WebSocket 事件日志

    Args:
        event_type: 事件类型
        client_id: 客户端 ID
        **kwargs: 其他参数
    """
    logger.bind(websocket=True).info(
        f"WebSocket 事件 - {event_type}",
        client_id=client_id,
        **kwargs
    )


def log_model_operation(operation: str, model_name: str, **kwargs: object) -> None:
    """
    记录模型操作日志

    Args:
        operation: 操作类型
        model_name: 模型名称
        **kwargs: 其他参数
    """
    logger.bind(model_operation=True).info(
        f"模型操作 - {operation}",
        model_name=model_name,
        **kwargs
    )


# 全局日志配置实例
logging_config = LoggingConfig()

# 便捷函数
def setup_logging(level: str = "INFO", enable_console: bool = True, enable_file: bool = True) -> None:
    """设置日志系统"""
    logging_config.setup(level=level, enable_console=enable_console, enable_file=enable_file)

def get_app_logger(name: Optional[str] = None) -> Any:
    """获取应用日志器"""
    return get_logger(name)
